#ifndef NETCLIENT_H
#define NETCLIENT_H

#include <QObject>
#include <QNetworkAccessManager>
#include <QWebSocket>
#include <QProtobufSerializer>
#include <QNetworkRePly>

#include "../model/data.h"

using namespace model;

//为了解决循环包含的问题，需要 前置声明 包含头文件
namespace model
{
class DataCenter;
} // end model

namespace network
{

class NetClient : public QObject
{
    Q_OBJECT
public:
    NetClient(model::DataCenter* dataCenter);

    // 验证网络联通
    void ping();

    // 初始化tWebsocket
    void initWebsocket();

    //身份认证
    void sendAuth();

    QString createRequestId();

    // 封装发送请求的逻辑
    QNetworkReply* sendHttpRequest(const QString& qpiPath,const QByteArray& body);

    // 封装处理响应的逻辑
    // 用输出型参数来表示是否ok 和 出错原因
    template<typename T>
    std::shared_ptr<T> handleHttpResponse(QNetworkReply* httpRsp,bool* ok,QString* reason)
    {
        if(httpRsp->error() != QNetworkReply::NoError) {
            *ok = false;
            *reason = httpRsp->errorString();
            return std::shared_ptr<T>();
        }

        // 获取到响应的rsp
        QByteArray rspBody = httpRsp->readAll();

        // 将body反序列化
        std::shared_ptr<T> rspObj = std::make_shared<T>();
        rspObj->deserialize(&serializer, rspBody);

        // 判断是否成功
        if(!rspObj->success()) {
            *ok = false;
            *reason = rspObj->errmsg();
            httpRsp->deleteLater();
            return std::shared_ptr<T>();
        }


        httpRsp->deleteLater();
        *ok = true;
        return rspObj;
    }

    void getMyself(const QString& loginSessionId);
    void getFriendList(const QString& loginSessionId);
    void getChatSessionList(const QString& loginSessionId);
    void getApplyList(const QString& loginSessionId);
    void getRecentMessageList(const QString& loginSessionId,const QString &chatSessionId, bool updateUI);
    void sendMessage(const QString &loginSessionId, const QString &chatSessionId, MessageType messageType,const QByteArray &content, const QString& extraInfo);

    void handleWsResponse(lch_im::NotifyMessage& notifyMessage);
    void handleWsMessage(const Message& message);
    void handleWsRemoveFriend(const QString& userId);
    void handleWsAddFriendApply(const UserInfo& userInfo);

    void receiveMessage(const QString& chatSessionId);
    void changeNickname(const QString& logSessionId,const QString& nickname);
    void changeDescription(const QString& loginSessionId,const QString& desc);
    void getVerifyCode(const QString& phone);
    void changePhone(const QString &loginSessionId, const QString &phone, const QString &verifyCodeId, const QString &verifyCode);
    void changeAvatar(const QString& loginSessionId, const QByteArray& avatar);
    void deleteFriend(const QString& loginSessionId,const QString& userId);
    void addFriendApply(const QString& loginSessionId,const QString& userId);
    void acceptFriendApply(const QString& loginSessionId,const QString& userId);
    void rejectFriendApply(const QString& loginSessionId,const QString& userId);
    void handleWsAddFriendProcess(const model::UserInfo &userInfo,bool agree);
    void createGroupChatSession(const QString& loginSessionId,const QList<QString>& userIdList);
    void handleWsSessionCreate(const ChatSessionInfo& chatSessionInfo);
    void searchUser(const QString& loginSessionId,const QString& text);
    void getMemberList(const QString& loginSessionId,const QString &chatSessionId);
    void searchMessage(const QString& loginSessionId,const QString& chatSessionId,const QString& searchKey);
    void searchMessageByTime(const QString& loginSessionId,const QString& chatSessionId,const QDateTime& begTime, const QDateTime& endTime);
    void userLogin(const QString& username,const QString& password);
    void userRegister(const QString& username,const QString& password);
    void phoneLogin(const QString &phone, const QString &verifyCodeId, const QString &verifyCode);
    void phoneRegister(const QString &phone, const QString &verifyCodeId, const QString &verifyCode);
    void getSingleFile(const QString& loginSessionId,const QString &fileId);
    void speechConvertText(const QString& loginSessionId, const QString& fileId, const QByteArray& content);
    //void exitGroupChatSession(const QString& logSessionId,const QString& chatSessionId,const QString& userId);
private:
    // 定义重要常量
    // const QString HTTP_URL = "http://47.109.159.231:9000";
    // const QString WEBSOCKET_URL = "ws://47.109.159.231:9001/ws";

    const QString HTTP_URL = "http://127.0.0.1:8000";
    const QString WEBSOCKET_URL = "ws://127.0.0.1:8001/ws";
private:
    model::DataCenter* dataCenter;
    // http 客户端
    QNetworkAccessManager httpClient;
    // websocket 客户端
    QWebSocket websocketClient;

    //序列化器
    QProtobufSerializer serializer;

signals:
};

} // end network

#endif // NETCLIENT_H


